#ifndef	_SPARCV9DECODE_H_
#define	_SPARCV9DECODE_H_

#pragma ident	"@(#)sparcv9decode.h	1.5	06/04/24 SMI"

#ifdef	__cplusplus
extern "C" {
#endif

/*
  * DBGELMIN will execute when DBG_EL_MIN or DBG_EL are set in debug_bits.
  * DBGEL will only execute if DBG_EL is set in debug_bits.
  */
#if DEBUG && !NDEBUG
#define	DBG_EL		0x2LL
#define	DBG_EL_MIN	0x4LL
#define	DBGEL(s)	do { if (debug_bits & (DBG_EL)) { s } } while (0)
#define	DBGELMIN(s)	do { if (debug_bits & (DBG_EL_MIN|DBG_EL)) { s } } while (0)
#define	DBG_ILLINST	0x10LL
#define	DBGILLINST(s)	do { if (debug_bits & (DBG_ILLINST)) { s } } while (0)
#else
#define	DBGEL(s)	do { } while (0)
#define	DBGELMIN(s)	do { } while (0)
#define	DBGILLINST(s)	do { } while (0)
#endif

#if !defined(NDEBUG)
#define	DBG_DECODE	0x40000000LL
#endif

	/*
	 * Principal instruction decoding for SPARC v9 instruction set.
	 * Eventually maybe v8 will be a defined subset of this.
	 */


typedef enum {
	illegal_instruction,
	unknown_instruction,
	unknown_fp_instruction,
	bpcc_illegal_cc_specifier,
	bpr_illegal_cc_specifier,
	done_retry_illegal_fcn_field,
	saved_fcn_invalid,
	saved_reserved_field_non_zero,
	tcc_reserved_field_non_zero,
	tcc_illegal_cc_field,
	movcc_reserved_field_non_zero,
	movcc_illegal_cc_field,
	movr_illegal_cc_field,
	odd_rd_for_ldd,
	odd_rd_for_std,
	fpop_bit13_set,
	illegal_fsr_specifier,
	unimplemented_visop,
	illtrap_reserved_field_non_zero,
	fmovcc_reserved_field_non_zero,
	fmovcc_illegal_cc_field,
	flushw_reserved_field_non_zero,
	visop36_reserved_field_non_zero,
	sir_reserved_field_non_zero,
	cas_reserved_field_non_zero
} v9_ill_instn_reason_t;




/*
 * Basic enumeration for the instruction types (op field) opcodes.
 */

typedef enum {
	Ty_0	= 0,	/* Branches and sethi */ /*The SPARC architecture manual defines sethi such that it destroys the least significant ten bits on encoding.*/ 
	Ty_1	= 1,	/* Call               */
	Ty_2	= 2,	/* Arithmetic & Misc  */
	Ty_3	= 3	/* Loads/Stores       */
} ty_code_t;




/*
 * An enumeration table for the op2 values for op==0
 */

typedef enum {
	T0o3_Illtrap = 0,	T0o3_BPcc,
	T0o3_Bicc,		T0o3_BPr,
	T0o3_SetHi,		T0o3_FBPfcc,
	T0o3_FBfcc,		T0o3_unknown_0x7
} T0o3_code_t;

/*
 * An enumeration table for the op3 values for op==2
 */

typedef enum {
    /* Col 0  (0x00 - 0x0f) */
        T2o3_add,	T2o3_and,	T2o3_or,	T2o3_xor,
        T2o3_sub,	T2o3_andn,	T2o3_orn,	T2o3_xnor,
        T2o3_addc,	T2o3_mulx,	T2o3_umul,	T2o3_smul,
        T2o3_subc,	T2o3_udivx,	T2o3_udiv,	T2o3_sdiv,
    /* Col 1  (0x10 - 0x1f) */
        T2o3_addcc,	T2o3_andcc,	T2o3_orcc,	T2o3_xorcc,
        T2o3_subcc,	T2o3_andncc,	T2o3_orncc,	T2o3_xnorcc,
        T2o3_addccc,	T2o3_unknown_0x19, T2o3_umulcc, T2o3_smulcc,
        T2o3_subccc,	T2o3_unknown_0x1d, T2o3_udivcc, T2o3_sdivcc,
    /* Col 2  (0x20 - 0x2f) */
        T2o3_taddcc,	T2o3_tsubcc,	T2o3_taddcctv, T2o3_tsubcctv,
        T2o3_mulscc,	T2o3_sll,	T2o3_srl,	T2o3_sra,
        T2o3_rdasr,	T2o3_rdhpr,	T2o3_rdpr,	T2o3_flushw,
        T2o3_movcc,	T2o3_sdivx,	T2o3_popc,	T2o3_movr,
    /* Col 3  (0x30 - 0x3f) */
        T2o3_wrasr,	T2o3_saved,	T2o3_wrpr,	T2o3_wrhpr,
        T2o3_fpop_0x34,	T2o3_fpop_0x35,	T2o3_gop,	T2o3_unknown_0x37,
        T2o3_jmpl,	T2o3_return,	T2o3_tcc,	T2o3_flush,
        T2o3_save,	T2o3_restore,	T2o3_retry,	T2o3_unknown_0x3f
} T2o3_code_t;

/*
 * Table of op3 values for the op=3 (load/store) opcodes
 */

typedef enum {
    /* Col 0 (0x00 - 0x0f) */
	T3o3_lduw, T3o3_ldub, T3o3_lduh, T3o3_ldd,
	T3o3_stw, T3o3_stb, T3o3_sth, T3o3_std,
	T3o3_ldsw, T3o3_ldsb, T3o3_ldsh, T3o3_ldx,
	T3o3_unknown_0x0c, T3o3_ldstub1, T3o3_stx, T3o3_swapd,
    /* Col 1 (0x10 - 0x1f) */
	T3o3_lduwa, T3o3_lduba, T3o3_lduha, T3o3_ldda,
	T3o3_stwa, T3o3_stba, T3o3_stha, T3o3_stda,
	T3o3_ldswa, T3o3_ldsba, T3o3_ldsha, T3o3_ldxa,
	T3o3_unknown_0x1c, T3o3_ldstuba, T3o3_stxa, T3o3_swapa,
    /* Col 2 (0x20 - 0x2f) */
	T3o3_ldf, T3o3_ldfsr, T3o3_ldqf, T3o3_lddf,
	T3o3_stf, T3o3_stfsr, T3o3_stqf, T3o3_stdf,
	T3o3_unknown_0x28, T3o3_unknown_0x29, T3o3_unknown_0x2a, T3o3_unknown_0x2b, 
	T3o3_unknown_0x2c, T3o3_prefetch, T3o3_unknown_0x2e, T3o3_unknown_0x2f,
    /* Col 3 (0x30 - 0x3f) */
	T3o3_ldfa, T3o3_unknown_0x31, T3o3_ldqfa, T3o3_lddfa,
	T3o3_stfa, T3o3_unknown_0x35, T3o3_stqfa, T3o3_stdfa,
	T3o3_unknown_0x38, T3o3_unknown_0x39, T3o3_unknown_0x3a, T3o3_unknown_0x3b, 
	T3o3_casa, T3o3_prefetcha, T3o3_casxa, T3o3_unknown_0x3f
} T3o3_code_t;


/*
 * Table of opf fields for the op=3, op3=0x34 floating point ops
 */

typedef enum {
	FPop34_fmovs	= 0x001,	FPop34_fmovd	= 0x002,	FPop34_fmovq	= 0x003,
	FPop34_fnegs	= 0x005,	FPop34_fnegd	= 0x006,	FPop34_fnegq	= 0x007,
	FPop34_fabss	= 0x009,	FPop34_fabsd	= 0x00a,	FPop34_fabsq	= 0x00b,
	FPop34_fsqrts	= 0x029,	FPop34_fsqrtd	= 0x02a,	FPop34_fsqrtq	= 0x02b,
	FPop34_fadds	= 0x041,	FPop34_faddd	= 0x042,	FPop34_faddq	= 0x043,
	FPop34_fsubs	= 0x045,	FPop34_fsubd	= 0x046,	FPop34_fsubq	= 0x047,
	FPop34_fmuls	= 0x049,	FPop34_fmuld	= 0x04a,	FPop34_fmulq	= 0x04b,
	FPop34_fdivs	= 0x04d,	FPop34_fdivd	= 0x04e,	FPop34_fdivq	= 0x04f,
	FPop34_fsmuld	= 0x069,	FPop34_fdmulq	= 0x06e,
	FPop34_fstox	= 0x081,	FPop34_fdtox	= 0x082,	FPop34_fqtox	= 0x083,
	FPop34_fxtos	= 0x084,	FPop34_fxtod	= 0x088,	FPop34_fxtoq	= 0x08c,
	FPop34_fitos	= 0x0c4,	FPop34_fdtos	= 0x0c6,	FPop34_fqtos	= 0x087,
	FPop34_fitod	= 0x0c8,	FPop34_fstod	= 0x0c9,	FPop34_fqtod	= 0x0cb,
	FPop34_fitoq	= 0x0cc,	FPop34_fstoq	= 0x0cd,	FPop34_fdtoq	= 0x0ce,
	FPop34_fstoi	= 0x0d1,	FPop34_fdtoi	= 0x0d2,	FPop34_fqtoi	= 0x0d3
} T3o3_fp34_opf_t;


/*
 * Table of opf fields for the op=3, op3=0x35 floating point ops
 */

typedef enum {
	FPop35_fmovrsz = 0x025, FPop35_fmovrdz = 0x026, FPop35_fmovrqz	= 0x027,
	FPop35_fmovrslez = 0x045, FPop35_fmovrdlez = 0x046, FPop35_fmovrqlez	= 0x047,
	FPop35_fmovrslz = 0x065, FPop35_fmovrdlz = 0x066, FPop35_fmovrqlz	= 0x067,
	FPop35_fmovrsnz = 0x0a5, FPop35_fmovrdnz = 0x0a6, FPop35_fmovrqnz	= 0x0a7,
	FPop35_fmovrsgz = 0x0c5, FPop35_fmovrdgz = 0x0c6, FPop35_fmovrqgz	= 0x0c7,
	FPop35_fmovrsgez = 0x0e5, FPop35_fmovrdgez = 0x0e6, FPop35_fmovrqgez	= 0x0e7,
	FPop35_fmovs_fcc0 = 0x001, FPop35_fmovd_fcc0 = 0x002, FPop35_fmovq_fcc0	= 0x003,
	FPop35_fmovs_fcc1 = 0x041, FPop35_fmovd_fcc1 = 0x042, FPop35_fmovq_fcc1	= 0x043,
	FPop35_fmovs_fcc2 = 0x081, FPop35_fmovd_fcc2 = 0x082, FPop35_fmovq_fcc2	= 0x083,
	FPop35_fmovs_fcc3 = 0x0c1, FPop35_fmovd_fcc3 = 0x0c2, FPop35_fmovq_fcc3	= 0x0c3,
	FPop35_fmovs_icc = 0x101, FPop35_fmovd_icc = 0x102, FPop35_fmovq_icc	= 0x103,
	FPop35_fmovs_xcc = 0x181, FPop35_fmovd_xcc = 0x182, FPop35_fmovq_xcc	= 0x183,
	FPop35_fcmps	= 0x051,	FPop35_fcmpd	= 0x052,	FPop35_fcmpq	= 0x053,
	FPop35_fcmpes	= 0x055,	FPop35_fcmped	= 0x056,	FPop35_fcmpeq	= 0x057
} T3o3_fp35_opf_t;


/*
 * Table of opf fields for the op=3, op3=0x36 vis ops
 */

typedef enum {
	VISop36_fzerod	= 0x060,
	VISop36_fzeros	= 0x061,	VISop36_foned	= 0x07e,	VISop36_fones	= 0x07f,
	VISop36_siam  = 0x81,
	VISop36_movdtox = 0x110, VISop36_movstouw = 0x111, VISop36_movstosw = 0x113,
	VISop36_movxtod = 0x118, VISop36_movwtos  = 0x119
} T3o3_fp36_opf_t;



typedef enum {
	Bcc_a   = 0x8,
	Bcc_n   = 0x0,
	Bcc_ne  = 0x9,
	Bcc_e   = 0x1,
	Bcc_g   = 0xA,
	Bcc_le  = 0x2,
	Bcc_ge  = 0xB,
	Bcc_l   = 0x3,
	Bcc_gu  = 0xC,
	Bcc_leu = 0x4,
	Bcc_cc  = 0xD,
	Bcc_cs  = 0x5,
	Bcc_pos = 0xE,
	Bcc_neg = 0x6,
	Bcc_vc  = 0xF,
	Bcc_vs  = 0x7
} bcc_type_t;

typedef enum {
	FBcc_a   = 0x8,
	FBcc_n   = 0x0,
	FBcc_e   = 0x9,
	FBcc_ne  = 0x1,
	FBcc_ue  = 0xA,
	FBcc_lg  = 0x2,
	FBcc_ge  = 0xB,
	FBcc_ul  = 0x3,
	FBcc_uge = 0xC,
	FBcc_l   = 0x4,
	FBcc_le  = 0xD,
	FBcc_ug  = 0x5,
	FBcc_ule = 0xE,
	FBcc_g   = 0x6,
	FBcc_o   = 0xF,
	FBcc_u   = 0x7
} fbcc_type_t;


typedef enum {
	RCond_reserved_0x0	= 0x0,
	RCond_z			= 0x1,
	RCond_lez		= 0x2,
	RCond_lz		= 0x3,
	RCond_reserved_0x4	= 0x4,
	RCond_nz		= 0x5,
	RCond_gz		= 0x6,
	RCond_gez		= 0x7
} rcond_type_t;



#if 0	
/**/
/* Support for the condition code computation*/
/**/

#define	CCODE_BIT_C	0
#define	CCODE_BIT_V	1
#define	CCODE_BIT_Z	2
#define	CCODE_BIT_N	3

#endif	/* } */







/*
 * Support macros for the instruction decoder
 */

	/* this is for an instruction - so everything is uint32_t */
	/* verify field [_e:_s] == 0 */

#define	RESERVED_FIELD(_e, _s)	( ((((uint32_t)0xffffffff)<<((_s)+31-(_e))) >> (31-(_e))) )
#define	CHECK_RESERVED_ZERO(_i, _e, _s)		\
	(( ((uint32_t)(_i)) & RESERVED_FIELD(_e, _s) ) == 0 )







#define X_OP(_i)		(((_i) >> 30) & 0x3)
#define	X_OP2(_i)		(((_i) >> 22) & 0x7)
#define	X_OP3(_i)		(((_i) >> 19) & 0x3f)
#define	X_FMT2_FCN(_i)		(((_i) >> 25) & 0x3f)

	/* 22bit immediate for seth_i */
#define	X_FMT2_IMM22(_i)		((_i) & 0x3FFFFF)

	/* Register fields */
#define	X_RS1(_i)		(((_i) >> 14) & 0x1f)
#define	X_RS2(_i)		(((_i) >> 0) & 0x1f)
#define	X_RD(_i)		(((_i) >> 25) & 0x1f)

	/* Immediate bit */
#define	X_I(_i)			(((_i) >> 13) & 0x1)

	/* ASI number */
#define	X_ASI(_i)		(((_i) >> 5) & 0xff)

	/* Nasty set of shifting to ensure we extract sign extended correctly */
#define	X_SIMM13(_i)		((((int)(_i))<<(8*sizeof(int)-13))>>(8*sizeof(int)-13))
#define	X_SIMM11(_i)		((((int)(_i))<<(8*sizeof(int)-11))>>(8*sizeof(int)-11))
#define	X_SIMM10(_i)		((((int)(_i))<<(8*sizeof(int)-10))>>(8*sizeof(int)-10))


#define	X_SHIFT_SIZE_BIT(_i)	(((_i) >> 12) & 0x1)

#define	X_SHIFT_IMM32(_i)	((_i) & 0x1f)
#define	X_SHIFT_IMM64(_i)	((_i) & 0x3f)

	/* For call instruction */
#define	X_FMT1_DISP30(_i)		((_i) & 0x3fffffff)

	/* For branches - the displacement, condition and annul bit */
#define	X_FMT2_DISP22(_i)	((_i) & 0x3FFFFF)
#define	X_FMT2_DISP19(_i)	((_i) & 0x7FFFF)
#define	X_FMT2_DISP16(_i)	(((_i) & 0x3FFF) | (((_i)>>6) & 0xc000))
#define	X_ANNUL_BIT(_i)		(((_i) >> 29) & 0x1)
#define	X_COND(_i)		(((_i)>>25) & 0xf)
#define	X_RCOND(_i)		(((_i)>>25) & 0x7)
#define	X_MOVRCOND(_i)		(((_i)>>10) & 0x7)

#define	X_FMT3_RCOND(_i)	(((_i) >> 10) & 0x7)

#define	X_FMT2_CC(_i)		(((_i) >>20) & 0x3)
typedef enum {
	CC2bit_icc	= 0x0,
	CC2bit_xcc	= 0x2
} cc2bit_t;

typedef enum {
	FCC2bit_fcc0	= 0x0,
	FCC2bit_fcc1	= 0x1,
	FCC2bit_fcc2	= 0x2,
	FCC2bit_fcc3	= 0x3
} fcc2bit_t;

#define	X_FMT4_CC(_i)		(((_i) >>11) & 0x3)
typedef enum {
	CC4bit_icc	= 0x0,
	CC4bit_xcc	= 0x2
} cc4bit_t;

	/* For the conditional move instructions */

#define	X_FMT4_CC2(_i)		(((_i)>>18)&1)	/* =0 if FPCC =1 if ICC */
#define	X_FMT4_CC2a(_i)		(((_i)>>13)&1)	/* =0 if FPCC =1 if ICC */
#define	X_FMT4_COND(_i)		(((_i)>>14)&0xf)

#define	X_MEMBAR_MASKS(_i)	((_i) & 0x7f)



	/* Format 3 - done and retry instructions */

#define	FMT3_FCN_SHIFT		25
#define	FMT3_FCN_MASK_BITS	5
#define	FMT3_FCN_MASK_BASE	((1LL<<FMT3_FCN_MASK_BITS)-1)
#define	X_FMT3_FCN(_i)		(((_i)>>FMT3_FCN_SHIFT)&FMT3_FCN_MASK_BASE)



	/*
	 * Floating point instructions
	 */

#define	FMT3_FP_OPF_SHIFT	5
#define	FMT3_FP_OPF_MASK	0x1ff
#define	X_FP_OPF( _i )		(((_i)>>FMT3_FP_OPF_SHIFT)&FMT3_FP_OPF_MASK)
#define	X_FCOND(_i)		(((_i)>>25) & 0x3)

/* rescale reg num for fp double regs */
#define	RESCALEFPREG(_R)	(_R) = ((_R) & 0x1e) | (((_R) & 1)<<5)

	/*
	 * setup for the xicache processing
	 */

#define	SET_OP(_n)	do { exec_funcp = decoded_impl_##_n ; } while (0)
#define	SET_OPv9(_n)	do { exec_funcp = decoded_impl_sparcv9_##_n ; } while (0)

#ifdef	__cplusplus
}
#endif

#endif /* _SPARCV9DECODE_H_ */
